﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Navigation;
using System.Windows.Data;
using System.Reflection;
using System.Collections;
using AdminModule.Views;
using SharedCode;
using AdminModule.IndexMarkServiceReference;
using System.ComponentModel;
using System.Collections.ObjectModel;
using AdminModule.CustomXAMLElements;
using AdminModule.ViewModels;
using AdminModule.CommonClasses;
using System.ServiceModel;

namespace AdminModule.Views
{
    public enum ViewName { AdmUnit, AdmTerm, AdmPerson, AdmJob, AdmStatus, AdmPosition, AdmCategoriesByTerm,
    AdmResponsible, AdmCharacteristic, AdmDepartment, AdmSection,
    AdmCategory, AdmGradation, AdmDepartmentType, AdmDegree, AdmPersonDegree};

    public partial class ViewData : Page
    {
        private ViewDataVM viewModel;

        private ViewName viewName;
        private Type currentType;
        private int? IDTerm;
        private ViewModelBase foreignViewModel;
        private object currentItem = null;

        // Объекты, отмеченные "галочками"
        private ObservableCollection<object> SelectedObjects = new ObservableCollection<object>();
        private ObservableCollection<CheckBox> CheckBoxes = new ObservableCollection<CheckBox>();

        // Лямбда-выражение, которое создает и инициализирует экземпляр класса
        Func<Type, DTOBase> ObjectCreator = (t) => Activator.CreateInstance(t) as DTOBase;

        // Делегат копирования объектов в другой период
        public delegate void CopyMethodDelegate(int fromIDTerm, int toIDTerm);
        private CopyMethodDelegate CopyMethod = (int fromIDTerm, int toIDTerm) => { };

        public EventsContainer events = new EventsContainer();

        private Dictionary<string, string> SidToNameCache = new Dictionary<string, string>();

        /// <summary>
        /// 
        /// </summary>
        /// <param name="currentType"></param>
        /// <param name="IDTerm"></param>
        /// <param name="foreignViewModel">Модель представления, из которой будут извлекаться данные для заполнения элементов ComboBox, например, для редактирования Jobs</param>
        public ViewData(ViewName viewName, int? IDTerm, ViewModelBase foreignViewModel)
        {
            InitializeComponent();

            SelectedObjects.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(SelectedObjects_CollectionChanged);
            dataGrid.SelectionChanged +=new SelectionChangedEventHandler(dataGrid_SelectionChanged);

            viewModel = Resources["viewDataViewModel"] as ViewDataVM;
            viewModel.LoadCompleted += new SharedCode.ViewModelBase.LoadEventHandler(viewModel_LoadCompleted);

            this.viewName = viewName;
            this.IDTerm = IDTerm;
            this.foreignViewModel = foreignViewModel;

            this.events.CopyStarted += () =>
                {
                    VisibleControls(false, "Копирование данных...");
                };
            this.events.CopyCompleted += (s, ev) =>
                {
                    VisibleControls(true);

                    if (ev.Error == null)
                        MessageBox.Show("Копирование успешно выполнено", MyAssemblyInfo.Title, MessageBoxButton.OK);
                    else
                        //MessageBox.Show("Не удалось выполнить копирование", MyAssemblyInfo.Title, MessageBoxButton.OK);
                        ErrorWindow.Show(ev.Error);
                };

            viewModel.client.GetNameBySidCompleted += new EventHandler<GetNameBySidCompletedEventArgs>(client_GetNameBySidCompleted);

            this.LoadData(viewName);
            
        }

        void client_GetNameBySidCompleted(object sender, GetNameBySidCompletedEventArgs e)
        {
            if (e.Result == string.Empty)
            {
                currentItem.GetType().GetProperty("SIDToName").SetValue(currentItem, "Не удалось получить имя. Возможно сервер не является членом домена.", null);
            }
            else
            {
                currentItem.GetType().GetProperty("SIDToName").SetValue(currentItem, e.Result, null);
                //SidToNameCache.Add(sid, e2.Result);
            }
        }

        void SelectedObjects_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
            UpdateButtons();
        }

        /// <summary>
        /// Вызывает окно редактирования и подписывается на событие завершения сохранения
        /// </summary>
        private void ShowEditWindow(object objectForEdit, EditMode editMode)
        {
            EditWindow editWindow;
            if (foreignViewModel != null)
            {
                editWindow = new EditWindow(this.viewName, editMode, Activator.CreateInstance(foreignViewModel.GetType()) as ViewModelBase);
            }
            else
            {
                editWindow = new EditWindow(this.viewName, editMode);
            }
            editWindow.SaveCompletedEvent += new EditWindow.SaveCompleted(editWindow_SaveCompletedEvent);
            editWindow.Show(objectForEdit);
        }

        private void SetTemplate(string templateName)
        {
            if (dataGrid.Columns.Count == 0)
            {
                foreach (var column in this.Resources["CheckBoxColumn"] as ColumnCollection)
                {
                    dataGrid.Columns.Add(column);
                }
                foreach (var column in this.Resources[templateName] as ColumnCollection)
                {
                    dataGrid.Columns.Add(column);
                }
            }
        }

        void viewModel_LoadCompleted(object sender, LoadEventArgs e)
        {
            VisibleControls(true);
        }

        void editWindow_SaveCompletedEvent(ViewName viewName)
        {
            this.LoadData(viewName);
        }

        public void LoadData(ViewName viewName)
        {
            events.RaiseBusyEvent(BusyEvent.LoadData);
            VisibleControls(false);

            switch (viewName)
            {
                case ViewName.AdmUnit:
                    SetTemplate("AdmUnit");
                    this.currentType = typeof(AdmUnit);
                    viewModel.client.GetAdmUnitsCompleted += (s, ev) =>
                        {
                            dataGrid.ItemsSource = new PagedCollectionView(ev.Result);
                            DataLoadCompleted();
                        };
                    viewModel.client.GetAdmUnitsAsync();
                    break;

                case ViewName.AdmTerm:
                    SetTemplate("AdmTerm");
                    this.currentType = typeof(AdmTerm);
                    viewModel.client.GetAdmTermsCompleted += (s, ev) =>
                        {
                            dataGrid.ItemsSource = new PagedCollectionView(ev.Result);
                            DataLoadCompleted();
                        };
                    viewModel.client.GetAdmTermsAsync();
                    break;

                case ViewName.AdmPerson:
                    SetTemplate("AdmPerson");
                    this.currentType = typeof(AdmPerson);
                    viewModel.client.GetAdmPersonsCompleted += (s, ev) =>
                        {
                            dataGrid.ItemsSource = new PagedCollectionView(ev.Result);
                            DataLoadCompleted();
                        };
                    viewModel.client.GetAdmPersonsAsync();
                    break;

                case ViewName.AdmDepartmentType:
                    SetTemplate("AdmDepartmentType");
                    this.currentType = typeof(AdmDepartmentType);
                    viewModel.client.GetAdmDepartmentTypesCompleted += (s, ev) =>
                    {
                        dataGrid.ItemsSource = new PagedCollectionView(ev.Result);
                        DataLoadCompleted();
                    };
                    viewModel.client.GetAdmDepartmentTypesAsync();
                    break;

                case ViewName.AdmJob:
                    SetTemplate("AdmJob");
                    this.currentType = typeof(AdmJob);
                    viewModel.client.GetAdmJobsCompleted += (s, ev) =>
                        {
                            dataGrid.ItemsSource = new PagedCollectionView(ev.Result);
                            DataLoadCompleted();
                        };
                    viewModel.client.GetAdmJobsAsync();
                    break;

                case ViewName.AdmStatus:
                    SetTemplate("AdmStatus");
                    this.currentType = typeof(AdmStatus);
                    viewModel.client.GetAdmStatusesCompleted += (s, ev) =>
                        {
                            dataGrid.ItemsSource = new PagedCollectionView(ev.Result);
                            DataLoadCompleted();
                        };
                    viewModel.client.GetAdmStatusesAsync();
                    break;

                case ViewName.AdmPosition:
                    SetTemplate("AdmPosition");
                    this.currentType = typeof(AdmPosition);
                    viewModel.client.GetAdmPositionsCompleted += (s, ev) =>
                        {
                            dataGrid.ItemsSource = new PagedCollectionView(ev.Result);
                            DataLoadCompleted();
                        };
                    viewModel.client.GetAdmPositionsAsync();
                    break;

                case ViewName.AdmCategoriesByTerm:
                    SetTemplate("AdmCategoriesByTerm");
                    this.currentType = typeof(AdmCategory);

                    CopyMethod = (int fromIDTerm, int toIDTerm) =>
                        {
                            events.RaiseBusyEvent(BusyEvent.Copy);
                            viewModel.client.CopyAdmCategoriesByTermAsync(fromIDTerm, toIDTerm);
                        };
                    viewModel.client.CopyAdmCategoriesByTermCompleted += (s, ev) =>
                        {
                            events.RaiseFreeEvent(FreeEvent.Copy, s, ev);
                        };

                    viewModel.client.GetAdmCategoriesByTermCompleted += (s, ev) =>
                        {
                            dataGrid.ItemsSource = new PagedCollectionView(ev.Result);
                            DataLoadCompleted();
                        };
                    ObjectCreator = (t) => new AdmCategory { IDTerm = (int)IDTerm };
                    viewModel.client.GetAdmCategoriesByTermAsync((int)IDTerm);

                    break;

               case ViewName.AdmPersonDegree:
                    SetTemplate("AdmPersonDegree");
                    this.currentType = typeof(AdmPersonDegree);

                    //copyButton.Visibility = System.Windows.Visibility.Visible;

                    CopyMethod = (int fromIDTerm, int toIDTerm) =>
                    {
                        events.RaiseBusyEvent(BusyEvent.Copy);
                        viewModel.client.CopyPersonDegreesAsync(fromIDTerm, toIDTerm);
                    };
                    viewModel.client.CopyPersonDegreesCompleted += (s, ev) =>
                    {
                        events.RaiseFreeEvent(FreeEvent.Copy, s, ev);
                    };

                    viewModel.client.GetAdmPersonDegreesCompleted += (s, ev) =>
                    {
                        dataGrid.ItemsSource = new PagedCollectionView(ev.Result);
                        DataLoadCompleted();
                    };
                    ObjectCreator = (t) => new AdmPersonDegree { IDTerm = (int)IDTerm };
                    viewModel.client.GetAdmPersonDegreesAsync((int)IDTerm);

                    break;

                case ViewName.AdmResponsible:
                    SetTemplate("AdmResponsible");
                    this.currentType = typeof(AdmResponsible);
                    viewModel.client.GetAdmResponsiblesCompleted += (s, ev) =>
                        {
                            dataGrid.ItemsSource = new PagedCollectionView(ev.Result);
                            DataLoadCompleted();
                        };
                    viewModel.client.GetAdmResponsiblesAsync();
                    break;

                case ViewName.AdmCharacteristic:
                    SetTemplate("AdmCharacteristic");
                    this.currentType = typeof(AdmCharacteristic);
                    viewModel.client.GetAdmCharacteristicsCompleted += (s, ev) =>
                        {
                            dataGrid.ItemsSource = new PagedCollectionView(ev.Result);
                            DataLoadCompleted();
                        };
                    viewModel.client.GetAdmCharacteristicsAsync();
                    break;

                case ViewName.AdmDepartment:
                    SetTemplate("AdmDepartment");
                    this.currentType = typeof(AdmDepartment);
                    viewModel.client.GetAdmDepartmentsCompleted += (s, ev) =>
                        {
                            dataGrid.ItemsSource = new PagedCollectionView(ev.Result);
                            DataLoadCompleted();
                        };
                    viewModel.client.GetAdmDepartmentsAsync(AdmDepartmentSortMode.TypeAndName);
                    break;

                case ViewName.AdmSection:
                    SetTemplate("AdmSection");
                    this.currentType = typeof(AdmSection);
                    viewModel.client.GetAdmSectionsCompleted += (s, ev) =>
                        {
                            dataGrid.ItemsSource = new PagedCollectionView(ev.Result);
                            DataLoadCompleted();
                        };
                    viewModel.client.GetAdmSectionsAsync();
                    break;

                case ViewName.AdmCategory:
                    SetTemplate("AdmCategory");
                    this.currentType = typeof(AdmCategory);
                    viewModel.client.GetAdmCategoriesCompleted += (s, ev) =>
                        {
                            dataGrid.ItemsSource = new PagedCollectionView(ev.Result);
                            DataLoadCompleted();
                        };
                    viewModel.client.GetAdmCategoriesAsync();
                    break;

                case ViewName.AdmGradation:
                    SetTemplate("AdmGradation");
                    this.currentType = typeof(AdmGradation);
                    viewModel.client.GetAdmGradationsCompleted += (s, ev) =>
                        {
                            dataGrid.ItemsSource = new PagedCollectionView(ev.Result);
                            DataLoadCompleted();
                        };
                   viewModel.client.GetAdmGradationsAsync();
                    break;

                case ViewName.AdmDegree:
                    SetTemplate("AdmDegree");
                    this.currentType = typeof(AdmDegree);
                    viewModel.client.GetAdmDegreesCompleted += (s, ev) =>
                    {
                        dataGrid.ItemsSource = new PagedCollectionView(ev.Result);
                        DataLoadCompleted();
                    };
                    viewModel.client.GetAdmDegreesAsync();
                    break;

                default:
                    throw new Exception("Справочника с таким названием не существует");
            }
        }

        private void DataLoadCompleted()
        {
            events.RaiseFreeEvent(FreeEvent.LoadData);
            VisibleControls(true);
        }

        // Executes when the user navigates to this page.
        protected override void OnNavigatedTo(NavigationEventArgs e)
        {

        }

        private void addButton_Click(object sender, RoutedEventArgs e)
        {
            DTOBase obj = ObjectCreator(currentType);
            if (obj == null) return;
            obj.State = StateObject.Created;
            ShowEditWindow(obj, EditMode.Add);
        }

        private void deleteButton_Click(object sender, RoutedEventArgs e)
        {
            if (this.SelectedObjects.Count == 0 && dataGrid.SelectedItem == null)
            {
                MessageBox.Show("Отметьте записи, которые необходимо удалить", MyAssemblyInfo.Title, MessageBoxButton.OK);
                return;
            }

            EditWindow f = new EditWindow(viewName, EditMode.Delete);
            f.SaveCompletedEvent += new EditWindow.SaveCompleted(editWindow_SaveCompletedEvent);

            if (this.SelectedObjects.Count == 0)
            {
                (dataGrid.SelectedItem as DTOBase).State = StateObject.Deleted;
                f.Show(new ObservableCollection<object> { dataGrid.SelectedItem });
            }
            else
            {
                foreach (DTOBase el in this.SelectedObjects)
                {
                    el.State = StateObject.Deleted;
                }
                f.Show(this.SelectedObjects);
            }
        }

        private void editButton_Click(object sender, RoutedEventArgs e)
        {
            DTOBase obj = dataGrid.SelectedItem as DTOBase;
            if (obj == null)
            {
                MessageBox.Show("Выберите запись, которую необходимо отредактировать", MyAssemblyInfo.Title, MessageBoxButton.OK);
                return;
            }
            obj.State = StateObject.Updated;
            ShowEditWindow(obj, EditMode.Edit);
        }

        private void dataGrid_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            UpdateButtons();
        }

        private void UpdateButtons()
        {
            this.deleteButton.IsEnabled = dataGrid.SelectedItem != null;
            this.editButton.IsEnabled = dataGrid.SelectedItem != null;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="isVisibility"></param>
        /// <param name="progressBarText">Если передается пустая строка, то устанавливается текст по умолчанию</param>
        private void VisibleControls(bool isVisibility, string progressBarText = "")
        {
            this.UpdateButtons();
            if (progressBarText == string.Empty)
                progressBar.SetDefaultText();
            else
                progressBar.Text = progressBarText;
            progressBar.IsVisibility = (isVisibility == true) ? Visibility.Collapsed : Visibility.Visible;
            buttonsPanel.Visibility = (isVisibility == true) ? Visibility.Visible : Visibility.Collapsed;
        }

        private void CheckBox_Checked(object sender, RoutedEventArgs e)
        {
            CheckBox checkBox = sender as CheckBox;
            if (checkBox.IsChecked == true)
            {
                if(!this.SelectedObjects.Contains(checkBox.Tag))
                    this.SelectedObjects.Add(checkBox.Tag);
            }
            else
            {
                this.SelectedObjects.Remove(checkBox.Tag);
            }
        }

        private void commonCheckBox_Checked(object sender, RoutedEventArgs e)
        {
            CheckBox checkBox = sender as CheckBox;
            foreach (var cb in this.CheckBoxes)
            {
                if (checkBox.IsChecked == true)
                    cb.IsChecked = true;
                else
                    cb.IsChecked = false;
            }
        }

        private void CheckBox_Loaded(object sender, RoutedEventArgs e)
        {
            if(!this.CheckBoxes.Contains(sender as CheckBox))
                this.CheckBoxes.Add(sender as CheckBox);
        }

        private void SIDToNameButton_Click(object sender, RoutedEventArgs e)
        {
            Button button = sender as Button;
            object element = button.Tag;
            object value = element.GetType().GetProperty("SIDForEdit").GetValue(element, null);
            currentItem = element;

            if (value == null || value.ToString().Trim() == string.Empty) return;

            string sid = value.ToString();

            element.GetType().GetProperty("SIDToName").SetValue(element, "Загрузка...", null);

            if (SidToNameCache.Keys.Contains(sid))
            {
                element.GetType().GetProperty("SIDToName").SetValue(element, SidToNameCache[sid], null);
            }
            else
            {
                viewModel.client.GetNameBySidAsync(sid);
            }
        }

        //private void SIDToNameButton_Loaded(object sender, RoutedEventArgs e)
        //{
        //    Button button = sender as Button;
        //    object element = button.Tag;
        //    object value = element.GetType().GetProperty("SIDForEdit").GetValue(element, null);

        //    if (value == null || value.ToString().Trim() == string.Empty) 
        //        button.Visibility = System.Windows.Visibility.Collapsed;
        //}

        private void copyButton_Click(object sender, RoutedEventArgs e)
        {
            switch (viewName)
            {
                case ViewName.AdmPersonDegree:
                    
                    break;
                default:
                    throw new Exception("Процедура копирования не определена");
            }
        }
    }
}
